package com.terren.statistic.common.util;

import java.io.EOFException;
import java.io.IOException;
import java.net.SocketTimeoutException;
import java.net.UnknownHostException;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.commons.httpclient.ConnectTimeoutException;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpHost;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.apache.log4j.Logger;

import com.terren.statistic.common.exception.TerrenSpiderException;



public class HttpClient {
	private static Logger logger = LogUtil.getLogger(HttpClient.class);
	private String siteHost;
	private int sitePort;
	private short timeout;
	private String charset;
	private String userAgent;
	private String cookie;
	private int statusCode;
	private Map<String, String> headerMap = new HashMap<String, String>();

	public HttpClient() {
		
	}
	
	public HttpClient(String siteHost, int sitePort) {
		this.siteHost = siteHost;
		this.sitePort = sitePort;		
	}
	
	public void setHost(String siteHost, int sitePort) {
		this.siteHost = siteHost;
		this.sitePort = sitePort;
	}
	
	public void setConfig(short timeout, String charset, String userAgent, String cookie) {
		this.timeout = timeout;
		this.charset = charset;
		this.userAgent = userAgent;
		this.cookie = cookie;
	}

	public void setTimeout(short timeout) {
		this.timeout = timeout;
	}

	public void setCharSet(String charset) {
		this.charset = charset;
	}

	public int getHttpStatusCode(){
		return this.statusCode;
	}
	
	public void setHeader(Map<String, String> headerMap) {
		this.headerMap = headerMap;
	}
	
	public String pageReader(String operation, String url, String referer) 
			throws Exception {
		
		HttpHost target = new HttpHost(siteHost, sitePort, "http");
		CloseableHttpClient httpclient = HttpClients.createDefault();
		String htmlText = null;
		try{
	        RequestConfig config = RequestConfig.custom()
	                .setSocketTimeout(timeout*1000)  //传输超时
	                .setConnectTimeout(60000) //连接超时
	                .build();
        
	        CloseableHttpResponse response; 
	        if(operation.equalsIgnoreCase("get")) {
	        	HttpGet httpGet = new HttpGet(url);
	        	httpGet.setConfig(config);
	        	if(headerMap.size() > 0) {
	        		for(Entry<String, String> e : headerMap.entrySet()) {
	        			httpGet.setHeader(e.getKey(), e.getValue());
	        		}
	        	}else {
					// 默认request头部信息
		        	httpGet.setHeader("User-Agent", userAgent);
		        	httpGet.setHeader("Accept-Language", "zh-CN,zh;q=0.5");
		        	httpGet.setHeader("Accept-Encoding", "gzip");
		        	httpGet.setHeader("Accept-Charset", "gbk,utf-8;q=0.7,*;q=0.7");
		        	httpGet.setHeader("Referer", referer);
		        	httpGet.setHeader("Cookie", cookie);
	        	}
		        response = httpclient.execute(target, httpGet);
	        }else{
	        	HttpPost httpPost = new HttpPost(url);
	        	httpPost.setConfig(config);
	        	if(headerMap.size() > 0) {
	        		for(Entry<String, String> e : headerMap.entrySet()) {
	        			httpPost.setHeader(e.getKey(), e.getValue());
	        		}	        		
	        	}else {
					// 默认request头部信息
		        	httpPost.setHeader("User-Agent", userAgent);
		        	httpPost.setHeader("Accept-Language", "zh-CN,zh;q=0.5");
		        	httpPost.setHeader("Accept-Encoding", "gzip");
		        	httpPost.setHeader("Accept-Charset", "gbk,utf-8;q=0.7,*;q=0.7");
		        	httpPost.setHeader("Referer", referer);
		        	httpPost.setHeader("Cookie", cookie);
	        	}

		        response = httpclient.execute(target, httpPost);
	        }
	        
	        try{
    	        Header headers[] = response.getAllHeaders();
    	        for(Header header : headers) {
    	        	logger.debug(header.toString());
    	        }
				HttpEntity entity = response.getEntity();
		
				logger.debug(response.getStatusLine() + " : " + url);
				statusCode = response.getStatusLine().getStatusCode();
				if(statusCode == 403) {
					throw new TerrenSpiderException(TerrenSpiderException.HTTP_403_EXCEPTION);
				}else if(statusCode == 414) {
					throw new TerrenSpiderException(TerrenSpiderException.HTTP_414_EXCEPTION);
				}else if(statusCode > 399 && statusCode < 500) {
					throw new TerrenSpiderException(TerrenSpiderException.HTTP_4XX_EXCEPTION);
				}else if(statusCode == 500) {
					throw new TerrenSpiderException(TerrenSpiderException.HTTP_500_EXCEPTION);
				}else if(statusCode > 499 && statusCode < 600) {
					throw new TerrenSpiderException(TerrenSpiderException.HTTP_5XX_EXCEPTION);
				}
				if (entity != null) {
					htmlText = EntityUtils.toString(entity,charset);
				}
	        }catch(EOFException e){
				logger.error("java.io.EOFException: "+url);
				throw e;
	        }finally{
	        	response.close();
	        }
		}
		catch(ConnectTimeoutException e){
			logger.error("ConnectTimeoutException: "+url+"\r\n"+e.getMessage());
			throw e;
		}catch(SocketTimeoutException e){
			logger.error("SocketTimeoutException: "+url+"\r\n"+e.getMessage());
			throw e;
		}
		catch(UnknownHostException e){
			logger.error("UnknownHostException: "+url+"\r\n"+e.getMessage());
			throw e;
		}catch(Exception e){
			logger.error(e.getMessage());
			throw e;
		}finally{
			try{
				httpclient.close();			
			}catch(IOException ie){
				ie.printStackTrace();
			}
		}
		return htmlText;
	}
}
